home *** CD-ROM | disk | FTP | other *** search
- '\"
- '\" Copyright 1989 Regents of the University of California
- '\" Permission to use, copy, modify, and distribute this
- '\" documentation for any purpose and without fee is hereby
- '\" granted, provided that this notice appears in all copies.
- '\" The University of California makes no representations about
- '\" the suitability of this material for any purpose. It is
- '\" provided "as is" without express or implied warranty.
- '\"
- '\" $Header: /user6/ouster/tcl/man/RCS/Fork.man,v 1.4 92/03/28 14:21:10 ouster Exp $ SPRITE (Berkeley)
- '\"
- .\" The definitions below are for supplemental macros used in Sprite
- .\" manual entries.
- .\"
- .\" .HS name section [date [version]]
- .\" Replacement for .TH in other man pages. See below for valid
- .\" section names.
- .\"
- .\" .AP type name in/out [indent]
- .\" Start paragraph describing an argument to a library procedure.
- .\" type is type of argument (int, etc.), in/out is either "in", "out",
- .\" or "in/out" to describe whether procedure reads or modifies arg,
- .\" and indent is equivalent to second arg of .IP (shouldn't ever be
- .\" needed; use .AS below instead)
- .\"
- .\" .AS [type [name]]
- .\" Give maximum sizes of arguments for setting tab stops. Type and
- .\" name are examples of largest possible arguments that will be passed
- .\" to .AP later. If args are omitted, default tab stops are used.
- .\"
- .\" .BS
- .\" Start box enclosure. From here until next .BE, everything will be
- .\" enclosed in one large box.
- .\"
- .\" .BE
- .\" End of box enclosure.
- .\"
- .\" .VS
- .\" Begin vertical sidebar, for use in marking newly-changed parts
- .\" of man pages.
- .\"
- .\" .VE
- .\" End of vertical sidebar.
- .\"
- .\" .DS
- .\" Begin an indented unfilled display.
- .\"
- .\" .DE
- .\" End of indented unfilled display.
- .\"
- '\" # Heading for Sprite man pages
- .de HS
- .if '\\$2'cmds' .TH \\$1 1 \\$3 \\$4
- .if '\\$2'lib' .TH \\$1 3 \\$3 \\$4
- .if '\\$2'tcl' .TH \\$1 3 \\$3 \\$4
- .if '\\$2'tk' .TH \\$1 3 \\$3 \\$4
- .if t .wh -1.3i ^B
- .nr ^l \\n(.l
- .ad b
- ..
- '\" # Start an argument description
- .de AP
- .ie !"\\$4"" .TP \\$4
- .el \{\
- . ie !"\\$2"" .TP \\n()Cu
- . el .TP 15
- .\}
- .ie !"\\$3"" \{\
- .ta \\n()Au \\n()Bu
- \&\\$1 \\fI\\$2\\fP (\\$3)
- .\".b
- .\}
- .el \{\
- .br
- .ie !"\\$2"" \{\
- \&\\$1 \\fI\\$2\\fP
- .\}
- .el \{\
- \&\\fI\\$1\\fP
- .\}
- .\}
- ..
- '\" # define tabbing values for .AP
- .de AS
- .nr )A 10n
- .if !"\\$1"" .nr )A \\w'\\$1'u+3n
- .nr )B \\n()Au+15n
- .\"
- .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
- .nr )C \\n()Bu+\\w'(in/out)'u+2n
- ..
- '\" # BS - start boxed text
- '\" # ^y = starting y location
- '\" # ^b = 1
- .de BS
- .br
- .mk ^y
- .nr ^b 1u
- .if n .nf
- .if n .ti 0
- .if n \l'\\n(.lu\(ul'
- .if n .fi
- ..
- '\" # BE - end boxed text (draw box now)
- .de BE
- .nf
- .ti 0
- .mk ^t
- .ie n \l'\\n(^lu\(ul'
- .el \{\
- .\" Draw four-sided box normally, but don't draw top of
- .\" box if the box started on an earlier page.
- .ie !\\n(^b-1 \{\
- \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
- .\}
- .el \}\
- \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
- .\}
- .\}
- .fi
- .br
- .nr ^b 0
- ..
- '\" # VS - start vertical sidebar
- '\" # ^Y = starting y location
- '\" # ^v = 1 (for troff; for nroff this doesn't matter)
- .de VS
- .mk ^Y
- .ie n 'mc \s12\(br\s0
- .el .nr ^v 1u
- ..
- '\" # VE - end of vertical sidebar
- .de VE
- .ie n 'mc
- .el \{\
- .ev 2
- .nf
- .ti 0
- .mk ^t
- \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
- .sp -1
- .fi
- .ev
- .\}
- .nr ^v 0
- ..
- '\" # Special macro to handle page bottom: finish off current
- '\" # box/sidebar if in box/sidebar mode, then invoked standard
- '\" # page bottom macro.
- .de ^B
- .ev 2
- 'ti 0
- 'nf
- .mk ^t
- .if \\n(^b \{\
- .\" Draw three-sided box if this is the box's first page,
- .\" draw two sides but no top otherwise.
- .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
- .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
- .\}
- .if \\n(^v \{\
- .nr ^x \\n(^tu+1v-\\n(^Yu
- \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
- .\}
- .bp
- 'fi
- .ev
- .if \\n(^b \{\
- .mk ^y
- .nr ^b 2
- .\}
- .if \\n(^v \{\
- .mk ^Y
- .\}
- ..
- '\" # DS - begin display
- .de DS
- .RS
- .nf
- .sp
- ..
- '\" # DE - end display
- .de DE
- .fi
- .RE
- .sp .5
- ..
- .HS Tcl_Fork tcl
- .BS
- .VS
- .SH NAME
- Tcl_Fork, Tcl_WaitPids, Tcl_DetachPids \- manage child processes
- .SH SYNOPSIS
- .nf
- \fB#include <tcl.h>\fR
- .sp
- int
- \fBTcl_Fork\fR( )
- .sp
- int
- \fBTcl_WaitPids\fR(\fInumPids, pidPtr, statusPtr\fR)
- .sp
- int
- \fBTcl_DetachPids\fR(\fInumPids, pidPtr\fR)
- .SH ARGUMENTS
- .AS int *statusPtr
- .AP int numPids in
- Number of process ids contained in the array pointed to by \fIpidPtr\fR.
- .AP int *pidPtr in
- Address of array containing \fInumPids\fR process ids.
- .AP int *statusPtr out
- Address of place to store status returned by exited/suspended process.
- .BE
-
- .SH DESCRIPTION
- .PP
- These procedures keep track of child processes in order to make it
- easier for one application to manage several children.
- If an application uses
- the UNIX \fIfork\fR and \fIwait\fR kernel calls directly,
- problems occur in situations like the following:
- .IP [1]
- One part of an application creates child C1. It plans to
- let the child run in background, then later wait for it to
- complete.
- .IP [2]
- Some other part of the application creates another child C2,
- not knowing anything about C1.
- .IP [3]
- The second part of the application uses \fIwait\fR to wait for C2
- to complete.
- .IP [4]
- C1 completes before C2, so C1 is returned by the
- \fIwait\fR kernel call.
- .IP [5]
- The second part of the application doesn't recognize C1, so it
- ignores it and calls \fIwait\fR again. This time C2
- completes.
- .IP [6]
- The first part of the application eventually decides to wait
- for its child to complete. When it calls \fIwait\fR there are
- no children left, so \fIwait\fR returns an error and the
- application never gets to examine the exit status for C1.
- .PP
- The procedures \fBTcl_Fork\fR, \fBTcl_WaitPids\fR, and \fBTcl_DetachPids\fR
- get around this problem by keeping a table of child processes and
- their exit statuses.
- They also provide a more flexible waiting
- mechanism than the \fIwait\fR kernel call.
- Tcl-based applications should never call \fIfork\fR and
- \fIwait\fR directly; they should use \fBTcl_Fork\fR,
- \fBTcl_WaitPids\fR, and \fBTcl_DetachPids\fR.
- .PP
- \fBTcl_Fork\fR calls \fIfork\fR and returns the result of
- the \fIfork\fR kernel call.
- If the \fIfork\fR call was successful then \fBTcl_Fork\fR also
- enters the new process into its internal table of child
- proceses.
- If \fIfork\fR returns an error then \fBTcl_Fork\fR returns that
- same error.
- .PP
- \fBTcl_WaitPids\fR calls \fIwait\fR repeatedly until one of the processes
- in the \fIpidPtr\fR array has exited or been killed or suspended by a
- signal.
- When this occurs, \fBTcl_WaitPids\fR returns the process
- identifier for the process and stores its wait status at
- \fI*statusPtr\fR.
- If the process no longer exists (it exited or was killed by a signal),
- then \fBTcl_WaitPids\fR removes its entry from the internal
- process table.
- If \fIwait\fR returns a process that isn't
- in the \fIpidPtr\fR array, \fBTcl_WaitPids\fR saves its wait
- status in the internal process table and calls \fIwait\fR again.
- If one of the processes in the \fIpidPtr\fR array has already
- exited (or suspended or been killed) when \fBTcl_WaitPids\fR
- is called, that process and its wait status are returned
- immediately without calling \fIwait\fR.
- .PP
- \fBTcl_WaitPids\fR provides two advantages. First, it allows
- processes to exit in any order, and saves their wait statuses.
- Second, it allows waiting on a number of processes simultaneously,
- returning when any of the processes is returned by \fIwait\fR.
- .PP
- \fBTcl_DetachPids\fR is used to indicate that the application
- no longer cares about the processes given by the \fIpidPtr\fR
- array and will never use \fBTcl_WaitPids\fR to wait for them.
- This occurs, for example, if one or more children are to be
- executed in background and the parent doesn't care whether
- they complete successfully.
- When \fBTcl_DetachPids\fR is called, the internal process
- table entries for the processes are marked so that the
- entries will be removed as soon as the processes exit or
- are killed.
- .PP
- If none of the pids passed to \fBTcl_WaitPids\fR exists in
- the internal process table, then -1 is returned and \fIerrno\fR
- is set to ECHILD.
- If a \fIwait\fR kernel call returns an error,
- then \fBTcl_WaitPids\fR returns that same error.
- If a \fIwait\fR kernel call returns a process that isn't in
- the internal process table, \fBTcl_WaitPids\fR panics and
- aborts the application.
- If this situation occurs, it means that a process has been
- created without calling \fBTcl_Fork\fR and that its exit
- status is about to be lost.
- .PP
- \fBTcl_WaitPids\fR defines wait statuses to have type \fIint\fR,
- which is correct for POSIX and many variants of UNIX.
- Some BSD-based UNIX systems still use type \fIunion wait\fR for
- wait statuses; it should be safe to cast a pointer to a
- \fIunion wait\fR structure to \fI(int *)\fR before passing
- it to \fBTcl_WaitPids\fR as in the following code:
- .nf
- .RS
-
- \fBunion wait status;
- int pid1, pid2;
- \&...
- pid2 = Tcl_WaitPids(1, &pid1, (int *) &status);\fR
- .RE
- .fi
-
- .SH KEYWORDS
- background, child, detach, fork, process, status, wait
- .VE
-